using System;
using System.ComponentModel;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.Design;

namespace Altairis.Web.UI.WebControls {

    [ToolboxData("<{0}:UsersDataSource runat=server />")]
    [Designer(typeof(UsersDataSourceDesigner))]
    public class UsersDataSource : DataSourceControl {
        private UsersView users;

        #region Parameters support (not currently used)

        /*
        private ParameterCollection parameters;

        private ParameterCollection Parameters {
            get {
                if (this.parameters == null) {
                    this.parameters = new ParameterCollection();
                    this.parameters.ParametersChanged += new EventHandler(this.OnParametersChanged);
                    if (this.IsTrackingViewState) ((IStateManager)this.parameters).TrackViewState();
                }
                return this.parameters;
            }
        }

        protected override void LoadViewState(object state) {
            object baseState = null;
            if (state != null) {
                Pair p = (Pair)state;
                baseState = p.First;
                if (p.Second != null) ((IStateManager)Parameters).LoadViewState(p.Second);
            }
            base.LoadViewState(baseState);
        }

        protected override void OnInit(EventArgs e) {
            Page.LoadComplete += new EventHandler(this.OnPageLoadComplete);
        }

        private void OnPageLoadComplete(object sender, EventArgs e) {
            if (this.parameters != null) this.parameters.UpdateValues(Context, this);
        }

        private void OnParametersChanged(object sender, EventArgs e) {
            if (this.users != null) this.users.RaiseChangedEvent();
        }

        protected override object SaveViewState() {
            object baseState = base.SaveViewState();
            object parameterState = null;

            if (this.parameters != null) {
                parameterState = ((IStateManager)this.parameters).SaveViewState();
            }

            if ((baseState != null) || (parameterState != null)) {
                return new Pair(baseState, parameterState);
            }
            return null;
        }

        protected override void TrackViewState() {
            base.TrackViewState();
            if (this.parameters != null) {
                ((IStateManager)this.parameters).TrackViewState();
            }
        }
        */

        #endregion Parameters support (not currently used)

        /// <summary>
        /// Gets the named data source view associated with the data source control.
        /// </summary>
        /// <param name="viewName">The name of the <see cref="T:System.Web.UI.DataSourceView"/> to retrieve. In data source controls that support only one view, such as <see cref="T:System.Web.UI.WebControls.SqlDataSource"/>, this parameter is ignored.</param>
        /// <returns>
        /// Returns the named <see cref="T:System.Web.UI.DataSourceView"/> associated with the <see cref="T:System.Web.UI.DataSourceControl"/>.
        /// </returns>
        protected override DataSourceView GetView(string viewName) {
            if (!string.IsNullOrEmpty(viewName) && !viewName.Equals("MembershipUsers", StringComparison.OrdinalIgnoreCase)) throw new ArgumentOutOfRangeException("viewName", viewName, "Specified view does not exists.");
            if (this.users == null) this.users = new UsersView(this, viewName);
            return this.users;
        }

        /// <summary>
        /// Gets a collection of names, representing the list of <see cref="T:System.Web.UI.DataSourceView"/> objects associated with the <see cref="T:System.Web.UI.DataSourceControl"/> control.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.ICollection"/> that contains the names of the <see cref="T:System.Web.UI.DataSourceView"/> objects associated with the <see cref="T:System.Web.UI.DataSourceControl"/>.
        /// </returns>
        protected override System.Collections.ICollection GetViewNames() {
            return new string[] { "MembershipUsers" };
        }

        private sealed class UsersView : DataSourceView {

            /// <summary>
            /// Initializes a new instance of the <see cref="UsersView"/> class.
            /// </summary>
            /// <param name="owner">The owner.</param>
            /// <param name="viewName">Name of the view.</param>
            public UsersView(UsersDataSource owner, string viewName) : base(owner, viewName) { }

            /// <summary>
            /// Raises the changed event.
            /// </summary>
            internal void RaiseChangedEvent() {
                this.OnDataSourceViewChanged(EventArgs.Empty);
            }

            /// <summary>
            /// Gets a list of data from the underlying data storage.
            /// </summary>
            /// <param name="arguments">A <see cref="T:System.Web.UI.DataSourceSelectArguments"/> that is used to request operations on the data beyond basic data retrieval.</param>
            /// <returns>
            /// An <see cref="T:System.Collections.IEnumerable"/> list of data from the underlying data storage.
            /// </returns>
            protected override System.Collections.IEnumerable ExecuteSelect(DataSourceSelectArguments arguments) {
                arguments.RaiseUnsupportedCapabilitiesError(this);

                return Membership.GetAllUsers();
            }
        }
    }

    public class UsersDataSourceDesigner : DataSourceDesigner {
        private UsersView users;

        /// <summary>
        /// Retrieves a <see cref="T:System.Web.UI.Design.DesignerDataSourceView"/> object that is identified by the view name.
        /// </summary>
        /// <param name="viewName">The name of the view.</param>
        /// <returns>This implementation always returns null.</returns>
        public override DesignerDataSourceView GetView(string viewName) {
            if (!string.IsNullOrEmpty(viewName) && !viewName.Equals("MembershipUsers", StringComparison.OrdinalIgnoreCase)) throw new ArgumentOutOfRangeException("viewName", viewName, "Specified view does not exists.");
            if (this.users == null) this.users = new UsersView(this, viewName);
            return this.users;
        }

        /// <summary>
        /// Returns an array of the view names that are available in this data source.
        /// </summary>
        /// <returns>An array of view names.</returns>
        public override string[] GetViewNames() {
            return new string[] { "MembershipUsers" };
        }

        private sealed class UsersView : DesignerDataSourceView {

            /// <summary>
            /// Initializes a new instance of the <see cref="UsersView"/> class.
            /// </summary>
            /// <param name="owner">The owner.</param>
            /// <param name="viewName">Name of the view.</param>
            public UsersView(UsersDataSourceDesigner owner, string viewName) : base(owner, viewName) { }

            /// <summary>
            /// Gets a schema that describes the data source view that is represented by this view object.
            /// </summary>
            /// <value></value>
            /// <returns>An <see cref="T:System.Web.UI.Design.IDataSourceViewSchema"/> object.</returns>
            public override IDataSourceViewSchema Schema {
                get {
                    TypeSchema ts = new TypeSchema(typeof(MembershipUser));
                    return ts.GetViews()[0];
                }
            }

            /// <summary>
            /// Generates design-time data that matches the schema of the associated data source control using the specified number of rows, indicating whether it is returning sample data or real data.
            /// </summary>
            /// <param name="minimumRows">The minimum number of rows to return.</param>
            /// <param name="isSampleData">true to indicate that the returned data is sample data; false to indicate that the returned data is live data.</param>
            /// <returns>
            /// A <see cref="T:System.Web.UI.DataSourceView"/> object containing data to display at design time.
            /// </returns>
            public override System.Collections.IEnumerable GetDesignTimeData(int minimumRows, out bool isSampleData) {
                if (minimumRows < 5) minimumRows = 5;
                isSampleData = true;
                MembershipUserCollection c = new MembershipUserCollection();
                for (int i = 1; i <= minimumRows; i++) {
                    c.Add(new MembershipUser(
                            "Provider Name", "User" + i, i, "user" + i + "@example.com", "Question #" + i, "Comment #" + i,
                            true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now)
                         );
                }
                return c;
            }
        }
    }
}